package jobs

import (
	"encoding/json"
	"fmt"
	"github.com/sirupsen/logrus"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"log"
	"regexp"
	"strings"
	"sync"
	"time"
	"wecom_rebot/common"
	"wecom_rebot/core"
	"wecom_rebot/models"
	"wecom_rebot/services"
)

const (
	batchSize = 10 // 每次获取的任务数量
)

var (
	consumerLogger *logrus.Logger // 只声明不初始化
	shutdownSignal = make(chan struct{})
	wg             sync.WaitGroup
)

type ReceiveRequest struct {
	Msgid   string   `json:"msgid" form:"msgid"`     // 消息id，消息的唯一标识，企业可以使用此字段进行消息去重。String类型
	Action  string   `json:"action" form:"action"`   // 消息动作，目前有send(发送消息)/recall(撤回消息)/switch(切换企业日志)三种类型。String类型
	From    string   `json:"from" form:"from"`       // 消息发送方id。同一企业内容为userid，非相同企业为external_userid。消息如果是机器人发出，也为external_userid。String类型
	Tolist  []string `json:"tolist" form:"tolist"`   // 消息接收方列表，可能是多个，同一个企业内容为userid，非相同企业为external_userid。数组，内容为string类型
	Roomid  string   `json:"roomid" form:"roomid"`   // 群聊消息的群id。如果是单聊则为空。String类型
	Msgtime int64    `json:"msgtime" form:"msgtime"` // 消息发送时间戳，utc时间，ms单位。
	Msgtype string   `json:"msgtype" form:"msgtype"` // 文本消息为：text。String类型
	Text    struct {
		Content string `json:"content"`
	} `json:"text" form:"text"` // 消息内容。String类型
}

type ParsedResult struct {
	SubjectName string
	Contents    map[string][]string
}

// InitConsumerLogger 移除 init() 函数，改为显式初始化函数
func InitConsumerLogger() {
	// 确保在 common 初始化后调用
	consumerLogger = core.InitLogger(common.LogsErrorMap[4])
}

// Worker 工作者协程
func Worker() {
	defer wg.Done()

	consumerLogger.Info("工作者启动")

	for {
		select {
		case <-shutdownSignal:
			consumerLogger.Info("收到停止信号，退出")
			return
		default:
			jobs, err := fetchJobs()
			if err != nil {
				consumerLogger.Error("获取任务失败", err)
				time.Sleep(2 * time.Second)
				continue
			}

			if len(jobs) == 0 {
				time.Sleep(1 * time.Second)
				continue
			}

			for _, job := range jobs {
				processJob(job)
			}
		}
	}
}

// 获取待处理任务（批量获取）
func fetchJobs() ([]models.Job, error) {
	var jobs []models.Job

	now := uint(time.Now().Unix())
	//lockExpiry := now - uint(lockDuration.Seconds())

	err := common.DB.Transaction(func(tx *gorm.DB) error {
		// 获取并锁定任务
		err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
			Where("status IN (10,20,30)").
			//Where("(reserved_at IS NULL OR reserved_at < ?)", lockExpiry).
			Where("reserved_at IS NULL").
			Where("available_at <= ?", now).
			Order("created_at ASC").
			Limit(batchSize).
			Find(&jobs).Error

		if err != nil {
			return err
		}

		consumerLogger.Info("获取任务的长度：", len(jobs))

		if len(jobs) == 0 {
			return nil
		}

		// 更新为锁定状态
		var jobIDs []uint64
		for _, job := range jobs {
			jobIDs = append(jobIDs, job.ID)
		}

		return tx.Model(&models.Job{}).
			Where("id IN ?", jobIDs).
			Updates(map[string]interface{}{
				"reserved_at": now,
				"attempts":    gorm.Expr("attempts + 1"),
				"status":      40,
			}).Error
	})

	return jobs, err
}

// 处理单个任务
func processJob(job models.Job) {

	var req ReceiveRequest

	// 解析任务数据
	if err := json.Unmarshal([]byte(job.Payload), &req); err != nil {
		consumerLogger.Error("解析任务数据失败", err, "job_id", job.ID)
		return
	}

	// 根据json中的数据 req.Text.Content 根据 \n 进行分组成一个数组，
	//{
	//    "msgid": "598835260023062777_1753099137222",
	//    "action": "send",
	//    "from": "wbWGQCCQAAppJtzj5FBSeP_dYyQi-3AA",
	//    "tolist": [
	//        "shyuyinbo",
	//        "shyinjiashuang",
	//        "18780208139",
	//        "18599409936",
	//        "15591610218",
	//        "scliuchi",
	//        "13568947196",
	//        "schewenjie",
	//        "13126650313",
	//        "15281265193",
	//        "sclinlan",
	//        "15082730141"
	//    ],
	//    "roomid": "wrWGQCCQAAFuO08aF22PB2uazwBxGzeQ",
	//    "msgtime": 1753099133021,
	//    "msgtype": "text",
	//    "text": {
	//    "content": "项目名称:脉搏跳动\n功能:复制户\n广告主ID:63595054\n复制数量:10\n媒介名字:苟小娟\n回复文件:否\n-----------------------------------\n复制成功数量：10\n复制成功：65338220,65338222,65338224,65338226,65338228,65338232,65338236,65338239,65338243,65338247"
	//  }
	//}

	// 拒绝直接删除
	if job.Status == 20 {
		err := common.DB.Model(&models.Job{}).Where("id = ?", job.ID).Delete(&job).Error
		if err != nil {
			consumerLogger.Error("删除任务失败", err, "job_id", job.ID)
		}
		return
	}

	setKey := strings.ReplaceAll(req.Text.Content, "：", ":")
	consumerLogger.Info("处理后内容：", setKey)
	consumerLogger.Info("处理后内容长度：", len(setKey))

	// 分割字符串
	parts := strings.Split(setKey, ":")

	if _, exists := SenderHandlerRegistry[parts[0]]; exists {
		handler := SenderHandlerRegistry[parts[0]]
		err := handler.Handle(req.Text.Content)
		if err != nil {
			consumerLogger.Error("处理任务失败", err, "job_id", job.ID)
			return
		}
		// 完成后进行删除当前任务
		err = common.DB.Model(&models.Job{}).Where("id = ?", job.ID).Delete(&job).Error
		if err != nil {
			consumerLogger.Printf("删除任务失败: %v", err)
			log.Printf("删除任务失败: %v", err)
		}
	}

	// 处理数据结构
	str := checkInternalAudit(&req)
	consumerLogger.Info("str：", str)
	if str == "" {
		return
	}

	var result ParsedResult

	switch str {
	case "复制户":
		result = parseText(req.Text.Content, "复制户")
		break
	case "巨量账户分配":
		result = parseText(req.Text.Content, "巨量账户分配")
		break
	case "巨量账户批量分配":
		result = parseText(req.Text.Content, "巨量账户批量分配")
		break
	case "巨量AD复制户":
		result = parseText(req.Text.Content, "巨量AD复制户")
		break
	case "巨量AD开户":
		result = parseText(req.Text.Content, "巨量AD开户")
		break
	case "巨量AD查询直客":
		result = parseText(req.Text.Content, "巨量AD查询直客")
		break
	case "巨量本地推复制户":
		result = parseText(req.Text.Content, "巨量本地推复制户")
		break
	case "巨量本地推开户":
		result = parseText(req.Text.Content, "巨量本地推开户")
		break
	case "巨量本地推查询直客":
		result = parseText(req.Text.Content, "巨量本地推查询直客")
		break
	case "巨量千川复制户":
		result = parseText(req.Text.Content, "巨量千川复制户")
		break
	case "巨量千川开户":
		result = parseText(req.Text.Content, "巨量千川开户")
		break
	case "巨量千川查询直客":
		result = parseText(req.Text.Content, "巨量千川查询直客")
		break
	case "快手复制户":
		result = parseText(req.Text.Content, "快手复制户")
		break
	case "快手验证码":
		result = parseText(req.Text.Content, "快手验证码")
		break
	case "绑定销售":
		result = parseText(req.Text.Content, "绑定销售")
		break
	case "小红书开户":
		result = parseText(req.Text.Content, "小红书开户")
		break
	case "小红书执照查询":
		result = parseText(req.Text.Content, "小红书执照查询")
		break
	}

	msgData := &models.Msg{
		WxMsgID: req.Roomid,
		Ts:      time.Now().Unix(),
		Type:    1,
		TypeStr: "文字",
		RoomID:  req.Roomid,
		Sender:  req.From,
		Content: req.Text.Content,
		Subject: result.SubjectName,
	}
	// 添加信息
	err := common.DB.Create(msgData).Error
	if err != nil {
		consumerLogger.Error("添加信息失败", err, "job_id", job.ID)
		return
	}

	errors := []string{}

	for key, values := range result.Contents {
		consumerLogger.Info("功能：", str, "job_id", job.ID, "key：", key, "values：", values)

		if _, exists := serviceRegistry[key]; !exists {
			errors = append(errors, fmt.Sprintf("功能:%s暂时不支持处理", key))
			continue
		}

		consumerLogger.Info("获取方法结果：", serviceRegistry[key])
		service := serviceRegistry[key]
		if err := service.Handle(msgData.ID, result.SubjectName, req.Roomid, values, job.ID); err != nil {
			// 移除功能行
			msgData.Content = services.RemoveTitle(msgData)
			errors = append(errors, fmt.Sprintf("%s\n-----------------------------------\n%s", msgData.Content, err))
		}
	}

	// 处理错误信息
	if len(errors) > 0 {
		for _, errorMsg := range errors {
			if err := services.BendiSendText(errorMsg, req.Roomid, req.From); err != nil {
				consumerLogger.Printf("发送错误消息失败: %v", err)
				log.Printf("发送错误消息失败: %v", err)
			}
		}
	}

	// 完成后进行删除当前任务
	err = common.DB.Model(&models.Job{}).Where("id = ?", job.ID).Delete(&job).Error
	if err != nil {
		consumerLogger.Printf("删除任务失败: %v", err)
		log.Printf("删除任务失败: %v", err)
	}
}

func checkInternalAudit(req *ReceiveRequest) string {
	// 预编译正则表达式（建议全局变量或sync.Once初始化）
	pattern := `功能[:：]\s*(复制户|巨量账户分配|巨量账户批量分配|巨量AD复制户|巨量AD开户|巨量AD查询直客|巨量本地推查询直客|巨量本地推复制户|巨量本地推开户|巨量千川查询直客|巨量千川复制户|巨量千川开户|快手复制户|快手验证码|绑定销售|小红书开户|小红书执照查询)`
	regex := regexp.MustCompile(pattern)

	// 执行匹配
	matches := regex.FindStringSubmatch(req.Text.Content)
	if len(matches) < 2 {
		return ""
	}

	// 匹配到的关键词
	keyword := matches[1]

	// 定义合法关键词集合
	validKeywords := map[string]struct{}{
		"复制户":       {},
		"巨量账户分配":    {},
		"巨量账户批量分配":  {},
		"巨量AD复制户":   {},
		"巨量AD开户":    {},
		"巨量AD查询直客":  {},
		"巨量本地推查询直客": {},
		"巨量本地推复制户":  {},
		"巨量本地推开户":   {},
		"巨量千川查询直客":  {},
		"巨量千川复制户":   {},
		"巨量千川开户":    {},
		"快手复制户":     {},
		"快手验证码":     {},
		"绑定销售":      {},
		"小红书开户":     {},
		"小红书执照查询":   {},
	}

	// 检查是否为有效关键词
	if _, exists := validKeywords[keyword]; exists {
		return keyword
	}

	return ""
}

func parseText(content string, subjectName string) ParsedResult {
	// 分割换行并处理每行内容
	contentLines := strings.Split(content, "\n")

	// 处理每行内容（替换中文冒号为英文冒号）
	for i, line := range contentLines {
		contentLines[i] = strings.ReplaceAll(line, "：", ":")
	}

	// 去除首行（索引0）
	//if len(contentLines) > 0 {
	//	contentLines = contentLines[1:]
	//}

	// 构建返回结构
	return ParsedResult{
		Contents: map[string][]string{
			subjectName: contentLines,
		},
		SubjectName: subjectName,
	}
}
